<template>
  <el-dialog
    v-model="dialogVisible"
    :title="isEdit ? '编辑表单字段' : '新增表单字段'"
    width="60%"
    @open="open"
    @closed="closed"
  >
    <el-form
      ref="formRef"
      :model="formField"
      label-width="120px"
      class="space-y-4"
    >
      <el-row :gutter="20">
        <el-col :span="12">
          <el-form-item label="字段类型" prop="type">
            <el-select
              v-model="type"
              placeholder="请选择字段类型"
              class="w-full"
              @change="typeChange"
            >
              <el-option
                v-for="type in typeOptions"
                :key="type.value"
                :label="type.label"
                :value="type.value"
              />
            </el-select>
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="字段名称" prop="label" required>
            <el-input v-model="formField.label" placeholder="请输入字段名称" />
          </el-form-item>
        </el-col>
      </el-row>

      <el-row :gutter="20">
        <el-col :span="12">
          <el-form-item label="字段标识" prop="prop" required>
            <el-input v-model="formField.prop" placeholder="请输入字段标识" />
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="是否必填" prop="required">
            <el-switch v-model="formField.required" />
          </el-form-item>
        </el-col>
      </el-row>

      <el-form-item v-if="requireOption.includes(type)" label="选项" required>
        <div class="border border-gray-200 rounded-md p-4 mb-4 w-full">
          <div class="flex justify-between items-center mb-4">
            <span class="font-medium">选项列表</span>
            <el-button
              type="primary"
              size="small"
              :icon="Plus"
              @click="addOption"
              >添加选项</el-button
            >
          </div>
          <el-table :data="formField.options" style="width: 100%">
            <el-table-column prop="label" label="选项标签">
              <template #default="{ row }">
                <el-input v-model="row.label" placeholder="选项标签" />
              </template>
            </el-table-column>
            <el-table-column prop="value" label="选项值">
              <template #default="{ row }">
                <el-input v-model="row.value" placeholder="选项值" />
              </template>
            </el-table-column>
            <el-table-column width="80">
              <template #default="{ $index }">
                <el-button
                  type="danger"
                  :icon="Delete"
                  circle
                  @click="removeOption($index)"
                />
              </template>
            </el-table-column>
          </el-table>
        </div>
      </el-form-item>

      <el-form-item label="验证规则">
        <div class="border border-gray-200 rounded-md p-4 mb-4 w-full">
          <div class="flex justify-between items-center mb-4">
            <span class="font-medium">规则列表</span>
            <el-button type="primary" size="small" :icon="Plus" @click="addRule"
              >添加规则</el-button
            >
          </div>
          <el-table :data="formField.rules" style="width: 100%">
            <el-table-column prop="rule" label="规则" width="180">
              <template #default="{ row }">
                <el-input
                  v-model="row.rule"
                  placeholder="输入正则表达式"
                  class="w-full"
                />
              </template>
            </el-table-column>
            <el-table-column prop="message" label="错误信息">
              <template #default="{ row }">
                <el-input v-model="row.message" placeholder="错误信息" />
              </template>
            </el-table-column>
            <el-table-column width="80">
              <template #default="{ $index }">
                <el-button
                  type="danger"
                  :icon="Delete"
                  circle
                  @click="removeRule($index)"
                />
              </template>
            </el-table-column>
          </el-table>
        </div>
      </el-form-item>

      <el-form-item v-if="type === 'input-number'" label="数字范围">
        <el-row :gutter="20">
          <el-col :span="8">
            <el-input-number
              v-model="formField.min"
              placeholder="最小值"
              class="w-full"
            />
          </el-col>
          <el-col :span="8">
            <el-input-number
              v-model="formField.max"
              placeholder="最大值"
              class="w-full"
            />
          </el-col>
          <el-col :span="8">
            <el-input-number
              v-model="formField.step"
              placeholder="步长"
              class="w-full"
            />
          </el-col>
        </el-row>
      </el-form-item>

      <el-form-item
        v-if="['upload', 'image-upload'].includes(type)"
        label="上传配置"
      >
        <div class="space-y-4">
          <el-input
            v-model="formField.action"
            placeholder="上传地址"
            class="mb-2"
          />
          <el-select
            v-model="formField.fileType"
            multiple
            filterable
            allow-create
            default-first-option
            placeholder="请选择或输入文件类型"
            class="mb-2 w-full"
          >
            <el-option
              v-for="item in fileTypeOptions"
              :key="item.value"
              :label="item.label"
              :value="item.value"
            />
          </el-select>
          <el-row :gutter="20">
            <el-col :span="12">
              <el-input-number
                v-model="formField.fileSize"
                placeholder="最大文件大小(MB)"
                class="w-full"
                :min="0.1"
                :step="0.1"
              />
            </el-col>
            <el-col :span="12">
              <el-input-number
                v-model="formField.limit"
                placeholder="上传数量限制"
                class="w-full"
                :min="1"
              />
            </el-col>
          </el-row>
        </div>
      </el-form-item>
    </el-form>
    <template #footer>
      <span class="flex justify-end space-x-2">
        <el-button @click="dialogVisible = false">取消</el-button>
        <el-button type="primary" @click="handleConfirm">确定</el-button>
      </span>
    </template>
  </el-dialog>
</template>

<script setup lang="ts">
import { ref, reactive, computed } from "vue";
import { Delete, Plus } from "@element-plus/icons-vue";
import { fileTypeOptions, FormField, requireOption, Type } from "./utils";
import { ElMessage, FormInstance } from "element-plus";

interface Props {
  modelValue: boolean;
  isEdit: boolean;
  editField?: FormField;
}

interface Emits {
  (e: "update:modelValue", value: boolean): void;
  (e: "confirm", field: FormField): void;
}

const props = defineProps<Props>();
const emit = defineEmits<Emits>();

const dialogVisible = computed({
  get() {
    return props.modelValue;
  },
  set(newValue) {
    emit("update:modelValue", newValue);
  }
});

const formRef = ref<FormInstance>();
const type = ref<Type>("input");

interface FormFieldForm extends Omit<FormField, "type"> {
  rules: { message: string; rule: string }[];
}

const formField = reactive<FormFieldForm>({
  label: "",
  prop: "",
  options: [],
  rules: [],
  required: false,
  min: -Infinity,
  max: Infinity,
  step: undefined,
  action: "",
  fileType: [],
  fileSize: 0.1,
  limit: 1
});

const typeChange = (value: Type) => {
  type.value = value;
  resetForm();
};
const typeOptions = [
  { label: "输入框", value: "input" },
  { label: "数字输入框", value: "input-number" },
  { label: "选择框", value: "select" },
  { label: "多选框", value: "multiple-select" },
  { label: "单选框", value: "radio" },
  { label: "复选框", value: "checkbox" },
  { label: "日期选择器", value: "date" },
  { label: "日期时间选择器", value: "date-time" },
  { label: "开关", value: "switch" },
  { label: "文件上传", value: "upload" },
  { label: "图片上传", value: "image-upload" }
];

const addOption = () => {
  if (!formField.options) {
    formField.options = [];
  }
  formField.options.push({ label: "", value: "" });
};

const removeOption = (index: number) => {
  formField.options?.splice(index, 1);
};

const addRule = () => {
  if (!formField.rules) {
    formField.rules = [];
  }
  formField.rules.push({ rule: "", message: "" });
};

const removeRule = (index: number) => {
  formField.rules?.splice(index, 1);
};

// 提交
const handleConfirm = () => {
  formRef.value?.validate(valid => {
    if (valid) {
      const finalField = { ...formField, type: type.value };
      // 选项数大于1
      if (requireOption.includes(finalField.type)) {
        if (finalField.options.length < 2) {
          ElMessage.error("选项数必须大于1");
          return;
        }
        // 选项是否有空
        if (finalField.options.some(el => !el.label || !el.value)) {
          ElMessage.error("选项不能为空");
          return;
        }
        // 选项是否有重复
        const valueArr = new Set(finalField.options.map(item => item.value));
        if (valueArr.size !== finalField.options.length) {
          ElMessage.error("选项值不能重复");
          return;
        }
      }
      if (finalField.rules) {
        finalField.rules = finalField.rules.map(rule => ({
          rule: rule.rule,
          message: rule.message
        }));
      }
      emit("confirm", finalField);
      dialogVisible.value = false;
    }
  });
};
const resetForm = () => {
  formRef.value?.resetFields();
  formField.rules = [];
  formField.options = [];
  formField.fileType = [];
};
const open = () => {
  if (props.isEdit && props.editField) {
    type.value = props.editField.type;
    for (const key in props.editField) {
      formField[key] = props.editField[key];
    }
  }
};

const closed = () => {
  resetForm();
};
</script>

<style scoped>
.el-form-item {
  margin-bottom: 22px;
}

.el-input-number {
  width: 100%;
}
</style>
